package com.onpositive.simple.persistance;

import static org.junit.Assert.assertTrue;

import java.lang.reflect.Array;
import java.util.HashSet;
import java.util.Random;

import junit.framework.TestCase;

import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.theories.internal.Assignments;
import java.lang.Math;

public class StorageTestRunner extends TestCase {
	
	RAMObjectStore<SampleObject> myStorage ;
	//FSObjectStore<SampleObject> myStorage ;
	
	@Before
	public void setUp(){
		
		myStorage = new RAMObjectStore<SampleObject>( SampleObject.class ) ;
		//myStorage = new FSObjectStore<SampleObject>( "C:\\test storage\\", SampleObject.class ) ;
		
		Thread s = new Thread() {
			private TreeViewer treeViewer;

			@Override
			public void run() {
				Display display = new Display() ;
				Shell shell = new Shell(display, SWT.SHELL_TRIM) ;
				shell.setLayout( new FillLayout() ) ;
				treeViewer = new TreeViewer(shell);
				shell.setSize(600, 600) ;
				
				treeViewer.setContentProvider(new ITreeContentProvider() {
					
					IntegerIndex myIndex = (IntegerIndex)myStorage.searchIndexArray[0] ;
					//StringIndex myIndex = (StringIndex)myStorage.searchIndexArray[1] ;
					@Override
					public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public void dispose() {
						// TODO Auto-generated method stub
						
					}
					
					@Override
					public boolean hasChildren(Object element) {
						// TODO Auto-generated method stub
						return true;
					}
					
					@Override
					public Object getParent(Object element) {
						// TODO Auto-generated method stub
						return null;
					}
					
					@Override
					public Object[] getElements(Object inputElement) {
						
						
						int rootIndex = myIndex.rootIndex ;
					    AbstractTreeNode node = myIndex.nodeStorage.getNode( rootIndex );
					    return new Object[]{ node };
					}
					
					@Override
					public Object[] getChildren(Object parentElement) {
						int emptySubtreeIndicator = myIndex.emptySubtreeIndicator ;
						int typeIndicatorBitsCount = myIndex.typeIndicatorBitsCount ;
						int zeroSubtreeOffset = myIndex.zeroSubtreeOffset ;
						RAMTreeNode parentNode = (RAMTreeNode)parentElement ;
						
						int recordsCount = parentNode.getElement(0) >> typeIndicatorBitsCount ;
						
						int childrenCount = 0 ;						
						for( int i = 0 ; i < recordsCount+1 ; i++  )
							if( parentNode.getElement(zeroSubtreeOffset + i) != emptySubtreeIndicator  )
								childrenCount++ ;
						
						Object result[] = new Object[ childrenCount ] ;
						
						int j = -1 ;
						for( int i = 0 ; i < recordsCount+1 ; i++  )
							if( parentNode.getElement(zeroSubtreeOffset + i) != emptySubtreeIndicator  )
								result[++j] = myIndex.nodeStorage.getNode( parentNode.getElement(zeroSubtreeOffset + i) ) ;
						
						return result;
					}
				}) ;
				treeViewer.setLabelProvider(new LabelProvider(){
					
					IntegerIndex intIndex = (IntegerIndex)myStorage.searchIndexArray[0] ;
					@Override
					public String getText(Object element) {
						
						int typeIndicatorBitsCount = intIndex.typeIndicatorBitsCount ;
						int zeroRecordOffset = intIndex.zeroRecordOffset ;
						int recSize = intIndex.recSize ;
						int idPos = intIndex.idPos ;
						int keyPos = intIndex.keyPos ;
						
						RAMTreeNode node = (RAMTreeNode) element ;
						
						int type = node.getElement(0) & ((1<<typeIndicatorBitsCount)-1) ;
						int recordsCount = node.getElement(0) >> typeIndicatorBitsCount ;
						
						String result = new String() ;
						result += node.index ;
						result+=", " ;
						result+= type ;
						result+="    " ;

						for( int i = 0 ; i < recordsCount ; i++ ){
							result += " : " ;
							result += node.getElement(zeroRecordOffset + i * recSize + keyPos ) ;
							result += "  " ;
							result += node.getElement(zeroRecordOffset + i * recSize + idPos  ) ;
							result += "  " ;
						}					
						return result ;
					}
					
				});
				treeViewer.setInput(StorageTestRunner.this ) ;
				Button r=new Button(shell, SWT.NONE);
				r.setText("Refresh");
				r.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						treeViewer.refresh(true);
					}
				});
				shell.open() ;
				while( !shell.isDisposed() ){
					
					if( !display.readAndDispatch() )
						display.sleep() ;
				}
				super.run();
			}
		};
		s.start() ;
		
		
	}
	@Test
	public void test01(){
		
		Random random = new Random(0) ;
		
		for( int i = 0 ; i < 10 ; i++ )
			myStorage.put(new SampleObject( random.nextInt(), ""+random.nextLong(),true ) );
		
		Filter lFilter = new Filter( Filter.GE, "id",  0 ) ;
		Filter rFilter = new Filter( Filter.LE, "id",  15000000 ) ;
		
		@SuppressWarnings("unused")
		int SR[] = myStorage.query("id", false, lFilter, rFilter ) ;
		
		assertTrue(true) ;
	}
//	
//	@Test
//	public void test02(){
//		
//		
//		SampleObject o0 = new SampleObject( 0, "1151", true  ) ;
//		SampleObject o1 = new SampleObject( 1, "1121", false ) ;
//		SampleObject o2 = new SampleObject( 2, "1211", true  ) ;
//		SampleObject o3 = new SampleObject( 3, "1112", false ) ;
//		SampleObject o4 = new SampleObject( 4, "1131", true  ) ;
//		SampleObject o5 = new SampleObject( 5, "1171", true  ) ;
//		SampleObject o6 = new SampleObject( 6, "1172", false ) ;
//		SampleObject o7 = new SampleObject( 7, "1201", true  ) ;
//		SampleObject o8 = new SampleObject( 8, "1232", false ) ;
//		SampleObject o9 = new SampleObject( 9, "1130", true  ) ;
//		
//		
//		int id0 = (Integer)myStorage.put(o0);
//		int id1 = (Integer)myStorage.put(o1);
//		int id2 = (Integer)myStorage.put(o2);
//		int id3 = (Integer)myStorage.put(o3);
//		int id4 = (Integer)myStorage.put(o4);
//		int id5 = (Integer)myStorage.put(o5);
//		int id6 = (Integer)myStorage.put(o6);
//		int id7 = (Integer)myStorage.put(o7);
//		int id8 = (Integer)myStorage.put(o8);
//		int id9 = (Integer)myStorage.put(o9);			
//				
//		int result0, result1, result2, result3, result4, result5, result6, result7, result8, result9 ;
//		
//		result0 = ((int[])myStorage.findByInt(0))[0] ;
//		result1 = ((int[])myStorage.findByInt(1))[0] ;
//		result2 = ((int[])myStorage.findByInt(2))[0] ;
//		result3 = ((int[])myStorage.findByInt(3))[0] ;
//		result4 = ((int[])myStorage.findByInt(4))[0] ;
//		result5 = ((int[])myStorage.findByInt(5))[0] ;
//		result6 = ((int[])myStorage.findByInt(6))[0] ;
//		result7 = ((int[])myStorage.findByInt(7))[0] ;
//		result8 = ((int[])myStorage.findByInt(8))[0] ;
//		result9 = ((int[])myStorage.findByInt(9))[0] ;			
//		
//		boolean test0 = (result0 == id0)&&(result1 == id1)&&(result2 == id2)&&(result3 == id3)&&(result4 == id4)
//						&&(result5 == id5) &&(result6 == id6) &&(result7 == id7)&&(result8 == id8)&&(result9 == id9) ; 
//		
//		result0 = ((int[])myStorage.findByString( "1151" ))[0] ;
//		result1 = ((int[])myStorage.findByString( "1121" ))[0] ;
//		result2 = ((int[])myStorage.findByString( "1211" ))[0] ;
//		result3 = ((int[])myStorage.findByString( "1112" ))[0] ;
//		result4 = ((int[])myStorage.findByString( "1131" ))[0] ;
//		result5 = ((int[])myStorage.findByString( "1171" ))[0] ;
//		result6 = ((int[])myStorage.findByString( "1172" ))[0] ;
//		result7 = ((int[])myStorage.findByString( "1201" ))[0] ;
//		result8 = ((int[])myStorage.findByString( "1232" ))[0] ;
//		result9 = ((int[])myStorage.findByString( "1130" ))[0] ;
//		
//		boolean test1 = (result0 == id0)&&(result1 == id1)&&(result2 == id2)&&(result3 == id3)&&(result4 == id4) 
//						&&(result5 == id5) &&(result6 == id6) &&(result7 == id7)&&(result8 == id8)&&(result9 == id9) ;
//		
//		assertTrue( test0 && test1 ) ;
//	}
//	
	@Test
	public void test02(){
	
	int objectsCount = 20 ;
		
	//int[] intFieldValue = { 0, 1, 15, 3, 4, 18, 6, 7, 19, 9, 10, 11, 12, 13, 14, 5, 16, 17 ,2, 8 } ;
	int[] intFieldValue = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 ,18, 19 } ;
	String[] stringFieldValue = { "1151", "1121", "1211", "1112", "1131", "1171", "1172", "1201", "1171", "1112",
			 					  "1151", "1121", "1211", "1112", "1131", "1171", "1172", "1201", "1171", "1112"  } ;
	boolean[] boolFieldValue = { true, false, true, false, true, true, false, true, false, true,
			                     true, false, true, false, true, true, false, true, false, true  } ;
	
	HashSet<Integer> intValues = new HashSet<Integer>() ;
	HashSet<String> stringValues = new HashSet<String>() ;
	for( int i = 0 ; i < objectsCount ; i++ ){
		intValues.add(intFieldValue[i]) ;
		stringValues.add(stringFieldValue[i]) ;
	}
	
	SampleObject testArray[] = new SampleObject[objectsCount] ;
	
	for( int i = 0 ; i < objectsCount ; i++ )
		testArray[i] = new SampleObject( intFieldValue[i], stringFieldValue[i], boolFieldValue[i]) ;
	
	int objectIndex[] = new int[objectsCount] ;
	
	for ( int i = 0 ; i < objectsCount ; i++ )
		objectIndex[i] = (Integer)myStorage.put( testArray[i] ) ;
	
	int[][] searchResult = new int[objectsCount][] ;
	
	Object sortedIntValuesObj = intValues.toArray() ;
	int sortedIntArrayLength = Array.getLength(sortedIntValuesObj) ;
	int sortedIntValues[] = new int[ sortedIntArrayLength ] ; 
	
	for( int i = 0 ; i < sortedIntArrayLength ; i++ )
		sortedIntValues[i] = (Integer)Array.get(sortedIntValuesObj, i) ;
	
	for ( int i = 0 ; i < sortedIntValues.length ; i++ )
		searchResult[i] = (int[])myStorage.findByInt( sortedIntValues[i] ) ;
	
	int result[] = new int[objectsCount] ;
	{
		int ind = -1 ;
		for( int i = 0 ; i < sortedIntValues.length ; i++ )
			for( int j = 0 ; j < searchResult[i].length ; j++ )
				result[++ind] = searchResult[i][j] ;
	}
	
	Filter lFilter = new Filter( Filter.GE, "id",  5 ) ;
	Filter rFilter = new Filter( Filter.LE, "id",  9 ) ;
	
	int SR[] = myStorage.query("id", false, lFilter, rFilter ) ;

	for ( int i = 0 ; i < objectsCount ; i++ )
		searchResult[i] = (int[])myStorage.findByString( stringFieldValue[i] ) ;
	
///		boolean test1 = (result0 == id0)&&(result1 == id1)&&(result2 == id2)&&(result3 == id3)&&(result4 == id4) 
//					&&(result5 == id5) &&(result6 == id6) &&(result7 == id7)&&(result8 == id8)&&(result9 == id9) ;
	
	assertTrue( true ) ;
}
	
	
		@Test
		public void test04(){
		
		int objectsCount = 12 ;
			
		int[] intFieldValue = { 0, 5, 4, 0, 2, 8, 0, 1, 8, 9, 3, 0 } ;
		String[] stringFieldValue = { "1151", "1121", "1211", "1112", "1131", "1171", "1172", "1201", "1171", "1112", "1121", "1211" } ;
		boolean[] boolFieldValue = { true, false, true, false, true, true, false, true, false, true, true, false } ;
		
		HashSet<Integer> intValues = new HashSet<Integer>() ;
		HashSet<String> stringValues = new HashSet<String>() ;
		for( int i = 0 ; i < objectsCount ; i++ ){
			intValues.add(intFieldValue[i]) ;
			stringValues.add(stringFieldValue[i]) ;
		}
		
		SampleObject testArray[] = new SampleObject[objectsCount] ;
		
		for( int i = 0 ; i < objectsCount ; i++ )
			testArray[i] = new SampleObject( intFieldValue[i], stringFieldValue[i], boolFieldValue[i]) ;
		
		int objectIndex[] = new int[objectsCount] ;
		
		for ( int i = 0 ; i < objectsCount ; i++ )
			objectIndex[i] = (Integer)myStorage.put( testArray[i] ) ;
		
		int[][] searchResult = new int[objectsCount][] ;
		
		Object sortedIntValuesObj = intValues.toArray() ;
		int sortedIntArrayLength = Array.getLength(sortedIntValuesObj) ;
		int sortedIntValues[] = new int[ sortedIntArrayLength ] ; 
		
		for( int i = 0 ; i < sortedIntArrayLength ; i++ )
			sortedIntValues[i] = (Integer)Array.get(sortedIntValuesObj, i) ;
		
		for ( int i = 0 ; i < sortedIntValues.length ; i++ )
			searchResult[i] = (int[])myStorage.findByInt( sortedIntValues[i] ) ;
		
		int result[] = new int[objectsCount] ;
		{
			int ind = -1 ;
			for( int i = 0 ; i < sortedIntValues.length ; i++ )
				for( int j = 0 ; j < searchResult[i].length ; j++ )
					result[++ind] = searchResult[i][j] ;
		}

		for ( int i = 0 ; i < objectsCount ; i++ )
			searchResult[i] = (int[])myStorage.findByString( stringFieldValue[i] ) ;
		
///		boolean test1 = (result0 == id0)&&(result1 == id1)&&(result2 == id2)&&(result3 == id3)&&(result4 == id4) 
//						&&(result5 == id5) &&(result6 == id6) &&(result7 == id7)&&(result8 == id8)&&(result9 == id9) ;
		
		assertTrue( true ) ;
	}
		
		
}
